package com.smartwebx.ha.dal.util;

import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.math3.stat.StatUtils;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.math.DoubleMath;
import com.smartwebx.ha.dal.usebean.DateValue;
import com.smartwebx.ha.dal.usebean.DateValueTotal;
import com.smartwebx.ha.dal.usebean.GisRain;
import com.smartwebx.ha.dal.usebean.abstr.AbstractTm;
import com.smartwebx.ha.dal.usebean.abstr.AbstractValue;

public class DateValueHandler {

	public static Ordering<AbstractValue> byValueOrder() {
		Ordering<AbstractValue> byVal = new Ordering<AbstractValue>() {
			@Override
			public int compare(AbstractValue left, AbstractValue right) {
				Double selfLeftVal = left.getVal();
				Double selfRightVal = right.getVal();
				return ObjectUtils.compare(selfLeftVal, selfRightVal);
			}
		};
		return byVal;
	}

	public static Ordering<AbstractTm> byTmOrder() {
		return new Ordering<AbstractTm>() {
			@Override
			public int compare(AbstractTm left, AbstractTm right) {
				return ObjectUtils.compare(left.getTm(), right.getTm());
			}
		};
	}

	public static Ordering<GisRain> byGisValueOrder() {
		Ordering<GisRain> byVal = new Ordering<GisRain>() {
			@Override
			public int compare(GisRain left, GisRain right) {
				Double selfLeftVal = left.getVal();
				Double selfRightVal = right.getVal();
				return ObjectUtils.compare(selfLeftVal, selfRightVal);
			}
		};
		return byVal;
	}

	public static Function<AbstractValue, Double> paserValFun() {
		return new Function<AbstractValue, Double>() {
			@Override
			public Double apply(AbstractValue input) {
				return Objects.firstNonNull(input.getVal(), 0d);
			}
		};
	}

	public static <T extends Number> Double avg(Iterable<Double> nums) {
		double avgNum = DoubleMath.mean(nums);
		return avgNum;
	}

	public static <T extends Number> Double avg(Iterable<Double> nums, long size) {
		Double sumNum = sum(nums);
		return sumNum / size;
	}

	public static <T extends AbstractValue> Double avgByObj(Iterable<T> objs,
			long size) {
		Iterable<Double> vals = Iterables.transform(objs,
				MyFunctions.getValueFuns());
		return avg(vals, size);
	}

	public static <T extends AbstractValue> Double avgByObj(Iterable<T> objs) {
		Iterable<Double> vals = Iterables.transform(objs,
				MyFunctions.getValueFuns());
		return avg(vals);
	}

	public static <T extends Number> Double sum(Iterable<Double> nums) {
		double[] numArr = ArrayUtils.toPrimitive(Iterables.toArray(nums,
				Double.class));
		double sumNum = StatUtils.sum(numArr);
		return sumNum;
	}

	public static <T extends AbstractValue> Double sumByObj(Iterable<T> objs) {
		Iterable<Double> vals = Iterables.transform(objs,
				MyFunctions.getValueFuns());
		return sum(vals);
	}

	public static void main(String args[]) {
		Date now = new Date();
		Random rand = new Random();
		List<DateValue> dvs = Lists.newArrayList();
		for (int i = 0; i < 10; i++) {
			int t = rand.nextInt(20);
			double d = rand.nextDouble();

			Date tNow = DateUtils.addHours(now, t);
			DateValue v1 = new DateValue();
			v1.setTm(tNow);
			v1.setVal(d);
			dvs.add(v1);
		}

		Ordering<AbstractTm> byTm = byTmOrder();
		Ordering<AbstractValue> byVal = byValueOrder();

		DateValue maxTm = byTm.max(dvs);
		DateValue minTm = byTm.min(dvs);

		DateValue maxVal = byVal.max(dvs);
		DateValue minVal = byVal.min(dvs);

		Iterable<Double> valList = Collections2.transform(dvs, paserValFun());
		Double avg = avg(valList);

		System.out.println(avg);
		System.out.println(maxTm);
		System.out.println(minTm);
		System.out.println(maxVal);
		System.out.println(minVal);

		List<DateValueTotal> dvts = Lists.transform(dvs,
				MyFunctions.transformDateValueTotal());
		for (DateValue dv : dvs) {
			System.out.println(dv.getVal());
		}
		System.out.println("----------------------------");
		for (DateValueTotal dvt : dvts) {
			System.out.println(dvt.getTotalVal());

		}

	}
}
